package com.swak.classloader;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * 测试类加载器
 * 
 * 1. 本例子是想测试自定义的 classloader 是否可以绕过父类加载器加载自定义的java.lang开头的类（实现覆盖的功能）。<br>
 * 2. 因为可以通过复写的方式绕过使用双亲委派的模式。<br>
 * 3. 但实际上不可以，对于加载的包，类加载会执行校验的过程。在校验的环节会校验是否以java开头。<br>
 * 4. 如果是以java开头则不能加载，因为这类类文件不是有java的类加载器加载的。<br>
 * 
 * @author lifeng
 */
public class MyClassLoader extends ClassLoader {

	@Override
	public Class<?> loadClass(String name) throws ClassNotFoundException {
		return super.loadClass(name);
	}

	@Override
	public Class<?> findClass(String name) throws ClassNotFoundException {
		File f = new File("D:\\swak_classloader",
				new StringBuilder(name.replaceAll("\\.", "/")).append(".class").toString());

		// 判断是否存在
		if (!f.exists()) {
			throw new RuntimeException("class not exists");
		}

		FileInputStream fis = null;
		ByteArrayOutputStream bos = null;
		try {
			fis = new FileInputStream(f);
			bos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int size = 0;
			while ((size = fis.read(buffer)) > 0) {
				bos.write(buffer, 0, size);
			}

			byte[] data = bos.toByteArray();
			return this.defineClass(name, data, 0, data.length);
		} catch (Exception e) {
			// 可以自定义一个异常抛出来
			throw new RuntimeException("load class error", e);
		} finally {
			this.closeQuietly(fis);
			this.closeQuietly(bos);
		}
	}

	public void closeQuietly(Closeable closeable) {
		try {
			if (closeable != null) {
				closeable.close();
			}
		} catch (IOException ioe) {
			// ignore
		}
	}
}
